
package com.rt.schedulenew.utils.ftp;

import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.slf4j.LoggerFactory;

import java.io.FileOutputStream;
import java.io.File;
import java.io.BufferedOutputStream;
import java.io.OutputStream;
import java.io.InputStream;

import org.apache.commons.net.ftp.FTPFile;

import java.util.ArrayList;
import java.util.List;
import java.io.IOException;

import org.apache.commons.net.ftp.FTPReply;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.net.ftp.FTPClient;
import org.slf4j.Logger;

public class FtpUtil {
    private static Logger log = LoggerFactory.getLogger(FtpUtil.class);
    public static final String[] charsets = new String[]{"UTF-8", "ISO-8859-1", "GBK", "GB2312"};
    private static final int BUFFER_SIZE = 2048;

    public static FTPClient createFtpClient(String ip, Integer port, String userName, String password, String encoding, int timeout) {
        FTPClient ftpClient = null;
        try {
            ftpClient = new FTPClient();
            if (StringUtils.isNotBlank((CharSequence) encoding)) {
                ftpClient.setControlEncoding(encoding);
            }
            if (timeout > 0) {
                ftpClient.setConnectTimeout(timeout);
            }
            ftpClient.connect(ip, (int) port);
            int reply = ftpClient.getReplyCode();
            if (!FTPReply.isPositiveCompletion(reply)) {
                ftpClient.disconnect();
                log.error("FTP登陆异常，错误码={}", (Object) reply);
                return null;
            }
            boolean result = ftpClient.login(userName, password);
            if (!result) {
                log.error("ftpClient登陆失败! userName:{}", (Object) userName);
            }
            ftpClient.setBufferSize(BUFFER_SIZE);
            ftpClient.setFileType(2);
            ftpClient.enterLocalPassiveMode();
            ftpClient.changeWorkingDirectory("/");
        } catch (IOException e) {
            log.error("创建ftp客户端失败，错误详情：{}", (Object) e.getMessage());
            return null;
        }
        return ftpClient;
    }

    public static FTPClient createFtpClient(String ip, Integer port, String userName, String password, String encoding) {
        return createFtpClient(ip, port, userName, password, encoding, 0);
    }

    public static FTPClient createFtpClient(String ip, Integer port, String userName, String password) {
        return createFtpClient(ip, port, userName, password, null, 0);
    }

    public static void destroyFtpClient(FTPClient ftpClient) {
        try {
            if (ftpClient != null && ftpClient.isConnected()) {
                ftpClient.logout();
                log.debug("ftp连接已关闭");
            }
        } catch (IOException e) {
            log.error("ftp连接关闭失败，错误详情：{}", (Object) e.getMessage());
            try {
                if (ftpClient != null) {
                    ftpClient.disconnect();
                }
            } catch (IOException io) {
                io.printStackTrace();
            }
        } finally {
            try {
                if (ftpClient != null) {
                    ftpClient.disconnect();
                }
            } catch (IOException io2) {
                log.error(io2.getMessage(), io2);
            }
        }
    }

    public static List<String> getFtpFileList(FTPClient ftpClient, String remoteDir) {
        List<String> filePathList = new ArrayList<String>();
        if (ftpClient == null || !ftpClient.isConnected()) {
            log.error("ftpClient为无效对象");
            return filePathList;
        }
        remoteDir = dirPathFormate(remoteDir);
        try {
            for (int i = 0; i < FtpUtil.charsets.length; ++i) {
                String charset = FtpUtil.charsets[i];
                ftpClient.setControlEncoding(charset);
                boolean changeDirFlag = ftpClient.changeWorkingDirectory(new String(remoteDir.getBytes(), charset));
                log.debug("远程目录：{}", (Object) remoteDir);
                log.debug("ftp实际切换到目录：{}", (Object) ftpClient.printWorkingDirectory());
                if (changeDirFlag) {
                    ftpClient.enterLocalPassiveMode();
                    FTPFile[] listFiles;
                    FTPFile[] ftpFiles = listFiles = ftpClient.listFiles();
                    for (FTPFile ftpFile : listFiles) {
                        if (ftpFile.isFile()) {
                            filePathList.add(remoteDir + ftpFile.getName());
                        }
                    }
                    return filePathList;
                }
                log.error("FTP切换目录失败，编码：{}，目录：{}", (Object) charset, (Object) remoteDir);
            }
        } catch (IOException e) {
            changeWorkingDirectoryToRoot(ftpClient);
            e.printStackTrace();
        }
        return filePathList;
    }

    public static List<FTPFile> getFtpFileInfoList(FTPClient ftpClient, String remoteDir) {
        List<FTPFile> fileInfoList = new ArrayList<FTPFile>();
        if (ftpClient == null || !ftpClient.isConnected()) {
            log.error("ftpClient为无效对象");
            return fileInfoList;
        }
        remoteDir = dirPathFormate(remoteDir);
        try {
            for (int i = 0; i < FtpUtil.charsets.length; ++i) {
                String charset = FtpUtil.charsets[i];
                ftpClient.setControlEncoding(charset);
                boolean changeDirFlag = ftpClient.changeWorkingDirectory(new String(remoteDir.getBytes(), charset));
                log.debug("远程目录：{}", (Object) remoteDir);
                log.debug("ftp实际切换到目录：{}", (Object) ftpClient.printWorkingDirectory());
                if (changeDirFlag) {
                    ftpClient.enterLocalPassiveMode();
                    FTPFile[] listFiles;
                    FTPFile[] ftpFiles = listFiles = ftpClient.listFiles();
                    for (FTPFile ftpFile : listFiles) {
                        if (ftpFile.isFile()) {
                            fileInfoList.add(ftpFile);
                        }
                    }
                    return fileInfoList;
                }
                log.error("FTP切换目录失败，编码：{}，目录：{}", (Object) charset, (Object) remoteDir);
            }
        } catch (IOException e) {
            changeWorkingDirectoryToRoot(ftpClient);
            e.printStackTrace();
        }
        return fileInfoList;
    }

    public static boolean createDir(FTPClient ftpClient, String remoteFileDir) {
        try {
            return ftpClient.makeDirectory(remoteFileDir);
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
    }

    public static boolean uploadFile(FTPClient ftpClient, String remoteFileDir, String fileName, InputStream ins) {
        if (StringUtils.isBlank((CharSequence) fileName) || ins == null || ftpClient == null) {
            log.error("非法的上传参数");
            return false;
        }
        remoteFileDir = filePathFormate(remoteFileDir);
        int index = 0;
        boolean changeDirFlag = false;
        while (index < 3) {
            ++index;
            for (int i = 0; i < FtpUtil.charsets.length; ++i) {
                try {
                    String charset = FtpUtil.charsets[i];
                    ftpClient.setControlEncoding(charset);
                    boolean makeDir = createDir(ftpClient, remoteFileDir);
                    if (makeDir) {
                        changeDirFlag = ftpClient.changeWorkingDirectory(remoteFileDir);
                        if (changeDirFlag) {
                            ftpClient.setFileType(2);
                            boolean storeFileFlag = ftpClient.storeFile(fileName, ins);
                            ins.close();
                            return storeFileFlag;
                        }
                    }
                } catch (Exception e) {
                    changeWorkingDirectoryToRoot(ftpClient);
                    e.printStackTrace();
                }
            }
        }
        return false;
    }

    public static boolean downloadFile(FTPClient ftpClient, String remoteFilePath, OutputStream out) {
        if (ftpClient == null || !ftpClient.isConnected()) {
            log.error("ftpClient为无效对象");
            return false;
        }
        remoteFilePath = filePathFormate(remoteFilePath);
        String remoteDir = getFileDir(remoteFilePath);
        BufferedOutputStream outBuff = new BufferedOutputStream(out);
        InputStream is = null;
        int index = 0;
        while (index < 3) {
            ++index;
            for (int i = 0; i < FtpUtil.charsets.length; ++i) {
                try {
                    String charset = FtpUtil.charsets[i];
                    ftpClient.setControlEncoding(charset);
                    boolean changeDirFlag = ftpClient.changeWorkingDirectory(new String(remoteDir.getBytes(), charset));
                    log.debug("远程目录：{}", (Object) remoteDir);
                    log.debug("ftp实际切换到目录：{}", (Object) ftpClient.printWorkingDirectory());
                    if (changeDirFlag) {
                        ftpClient.enterLocalPassiveMode();
                        FTPFile[] ftpFiles = ftpClient.listFiles();
                        FTPFile fFile = null;
                        for (FTPFile ftpFile : ftpFiles) {
                            String fileName = getFileName(remoteFilePath);
                            if (fileName.equals(ftpFile.getName())) {
                                fFile = ftpFile;
                                break;
                            }
                        }
                        if (fFile == null) {
                            log.error("文件下载失败，文件不存在，文件路径：{}", (Object) remoteFilePath);
                            return false;
                        }
                        is = ftpClient.retrieveFileStream(fFile.getName());
                        IOUtils.copy(is, outBuff);
                        outBuff.flush();
                        outBuff.close();
                        out.close();
                        is.close();
                        index = 3;
                        ftpClient.completePendingCommand();
                        log.debug("{}文件下载成功：{}", (Object) fFile.getName());
                        return true;
                    } else {
                        changeWorkingDirectoryToRoot(ftpClient);
                        log.error("FTP切换目录失败，编码：{}，目录：{}", (Object) charset, (Object) remoteFilePath);
                    }
                } catch (IOException e) {
                    changeWorkingDirectoryToRoot(ftpClient);
                    log.error("文件下载失败，远程目录：{}，错误详情：{}", (Object) remoteFilePath, (Object) e.getMessage());
                } finally {
                    if (outBuff != null) {
                        try {
                            outBuff.close();
                        } catch (IOException ex) {
                        }
                    }
                    if (out != null) {
                        try {
                            out.close();
                        } catch (IOException ex2) {
                        }
                    }
                    if (is != null) {
                        try {
                            is.close();
                        } catch (IOException ex3) {
                        }
                    }
                }
            }
        }
        return false;
    }

    public static boolean downloadFile(FTPClient ftpClient, String remoteFilePath, String localFilePath) {
        if (ftpClient == null) {
            return false;
        }
        localFilePath = filePathFormate(localFilePath);
        File localFile = new File(localFilePath);
        try {
            localFile.getParentFile().mkdirs();
            FileOutputStream ops = new FileOutputStream(localFile);
            return downloadFile(ftpClient, remoteFilePath, ops);
        } catch (Exception e) {
            log.error("文件下载失败，远程目录：{}，本地目录：{}，错误详情：{}", new Object[]{remoteFilePath, localFilePath, e.getMessage()});
            return false;
        }
    }

    public static boolean existFile(FTPClient ftpClient, String remoteFilePath) {
        if (ftpClient == null || !ftpClient.isConnected()) {
            log.error("ftpClient为无效对象");
            return false;
        }
        remoteFilePath = filePathFormate(remoteFilePath);
        String remoteDir = getFileDir(remoteFilePath);
        for (int i = 0; i < FtpUtil.charsets.length; ++i) {
            try {
                String charset = FtpUtil.charsets[i];
                ftpClient.setControlEncoding(charset);
                boolean changeDirFlag = ftpClient.changeWorkingDirectory(new String(remoteDir.getBytes(), charset));
                log.debug("ftp远程目录：{}", (Object) remoteDir);
                log.debug("ftp实际切换到目录：{}", (Object) ftpClient.printWorkingDirectory());
                if (changeDirFlag) {
                    ftpClient.enterLocalPassiveMode();
                    FTPFile[] listFiles;
                    FTPFile[] ftpFiles = listFiles = ftpClient.listFiles();
                    for (FTPFile ftpFile : listFiles) {
                        String fileName = getFileName(remoteFilePath);
                        if (fileName.equals(ftpFile.getName())) {
                            return true;
                        }
                    }
                    break;
                }
                log.error("FTP切换目录失败，编码：{}，目录：{}", (Object) charset, (Object) remoteFilePath);
            } catch (IOException e) {
                changeWorkingDirectoryToRoot(ftpClient);
                e.printStackTrace();
            }
        }
        return false;
    }

    public static boolean changeWorkingDirectoryToRoot(FTPClient ftpClient) {
        boolean flag = false;
        try {
            while (!flag) {
                ftpClient.changeToParentDirectory();
                String dir = ftpClient.printWorkingDirectory();
                if (dir == null || "/".equals(dir)) {
                    flag = true;
                }
            }
        } catch (IOException e) {
            log.error("ftp切换到根目录失败，错误详情：{}", (Object) e.getMessage());
        }
        return flag;
    }

    private static String getFileName(String filePath) {
        filePath = filePathFormate(filePath);
        if (StringUtils.isBlank((CharSequence) filePath)) {
            return "";
        }
        int index = filePath.lastIndexOf("/");
        if (index == -1) {
            return filePath;
        }
        String fileName = filePath.substring(index + 1, filePath.length());
        return fileName;
    }

    private static String getFileDir(String filePath) {
        filePath = filePathFormate(filePath);
        if (StringUtils.isBlank((CharSequence) filePath)) {
            return "/";
        }
        int index = filePath.lastIndexOf("/");
        if (index == -1) {
            return filePath;
        }
        String fileDir = filePath.substring(0, index + 1);
        return fileDir;
    }

    private static boolean delDir(File dir) {
        if (dir.isDirectory()) {
            log.info("定时删除缓存影像目录，路径：{}", (Object) dir.getAbsolutePath());
            String[] children = dir.list();
            for (int i = 0; i < children.length; ++i) {
                boolean success = delDir(new File(dir, children[i]));
                if (!success) {
                    return false;
                }
            }
        }
        if (dir.delete()) {
            return true;
        }
        log.error("定时删除缓存影像目录失败，路径：{}", (Object) dir.getAbsolutePath());
        return false;
    }

    private static String dirPathFormate(String dirPath) {
        dirPath = dirPath.replace("\\", "/");
        dirPath = (dirPath.endsWith("/") ? dirPath : (dirPath + "/"));
        return dirPath;
    }

    private static String filePathFormate(String filePath) {
        filePath = filePath.replace("\\", "/");
        return filePath;
    }
}
